package com.bluewap.api;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import com.bluewap.api.object.Transaction;
import com.bluewap.core.AESGenerator;
import com.bluewap.core.Database;
import com.bluewap.core.StaticVar;
import com.bluewap.core.Util;

public class OrderServlet extends HttpServlet {
	private static final long serialVersionUID = -3996888612424895513L;
	private Logger log = Logger.getLogger("order");
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
	throws ServletException, IOException {
		String cpId = req.getParameter("cpid");
		String param = req.getParameter("param");

		if(!Util.isValidParam(param) || !Util.isValidParam(cpId)){
			log.info(StaticVar.ERROR_PARAM_MISSING + "|" + req.getQueryString());
			Util.printJson(StaticVar.ERROR_PARAM_MISSING, null, resp);
			return;
		}
		// Check CP status & aeskey
		int cpStatus = 0;
		String cpAeskey = "";		

		Connection conn = Database.getConnection();
		PreparedStatement st = null;
		PreparedStatement st1 = null;
		ResultSet rs = null;
		try {
		   
			String query = "SELECT AESKEY, STATUS FROM CONTENTPROVIDERS WHERE ID = ?" ;
			st = conn.prepareStatement(query);
			st.setInt(1, Integer.valueOf(cpId));
			
			rs = st.executeQuery();
			while(rs.next()){
				
				cpAeskey = rs.getString(StaticVar.DB_CP_AESKEY);
				cpStatus = rs.getInt(StaticVar.DB_CP_STATUS);
				break;
			}

		} catch (Exception e) {
			log.error("Error", e);
			e.printStackTrace();
		} finally{
			try {
				if (rs != null)	rs.close();
				if (st != null)	st.close();
				if (conn != null)	Database.closeConnection(conn);
			} catch (Exception e) {
				log.error("Error", e);
			}
		}
		if(cpAeskey.length() == 0) {
			log.info(StaticVar.ERROR_CP_NOT_FOUND + "|" + req.getQueryString());
			Util.printJson(StaticVar.ERROR_CP_NOT_FOUND, null, resp);

			return;
		}
		else if(cpStatus == 0){
			log.info(StaticVar.ERROR_CP_SUSPENDED + "|" + req.getQueryString());
			Util.printJson(StaticVar.ERROR_CP_SUSPENDED, null, resp);

			return;
		}

		// decrypt using aeskey
		int orderStatus = StaticVar.ERROR_ORDERED;

		String decryptParam = AESGenerator.decrypt(param.replace(" ", "+"), cpAeskey);
		String[] field = null;

		if(!Util.isValidParam(decryptParam)){
			orderStatus = StaticVar.ERROR_PARAM_DECRYPT_ERROR;
			log.info(StaticVar.ERROR_PARAM_DECRYPT_ERROR + "|" + req.getQueryString());

			Util.printJson(StaticVar.ERROR_PARAM_DECRYPT_ERROR, null, resp);
		}
		else{
			field = decryptParam.split(";");
			if(field.length != 5) {
				orderStatus = StaticVar.ERROR_PARAM_DECRYPT_MISSING;
				log.info(StaticVar.ERROR_PARAM_DECRYPT_MISSING + "|" + req.getQueryString());

				Util.printJson(StaticVar.ERROR_PARAM_DECRYPT_MISSING, null, resp);	
			}
		}
		
		// insert to DB
		int transId = 0;
		conn = Database.getConnection();
		try{
					
			String query = "INSERT INTO" +
			" INCOMINGS (CP_ID, PARAM, STATUS)" +
			" VALUES (?,?,?)";
			st = conn.prepareStatement(query,Statement.RETURN_GENERATED_KEYS);
			st.setInt(1, Integer.valueOf(cpId));
			st.setString(2, param);
			st.setInt(3, Integer.valueOf(orderStatus));
			
			st.executeUpdate();
			
			rs = st.getGeneratedKeys();
            
			if(rs.next()) {
				transId = rs.getInt(1);
			}
		} catch(Exception e){
			log.error("Error", e);
			Util.printJson(StaticVar.ERROR_INTERNAL_ERROR, null, resp);	
			return;			
		} finally{
			try {
				if (rs != null)	rs.close();
				if (st != null)	st.close();
				if (conn != null)	Database.closeConnection(conn);
			} catch (Exception e) {
				log.error("Error", e);		
			}			
		}		

		if(orderStatus == StaticVar.ERROR_ORDERED){
			String returnURL = field[0];
			String contentId = field[1];
			String contentName = field[2];
			String contentType = field[3];
			String contentPrice = field[4];

			if(!(Util.isValidParam(contentId)
					&& Util.isValidParam(contentName)
					&& Util.isValidType(contentType)
					&& Util.isValidPrice(contentPrice)
					&& Util.isValidUrl(returnURL))){
				log.info(StaticVar.ERROR_PARAM_DECRYPT_MISSING + "|" + req.getQueryString());

				Util.printJson(StaticVar.ERROR_PARAM_DECRYPT_MISSING, null, resp);	

				return;
			}
			else{
				conn = Database.getConnection();
				try {
					
					String token = UUID.randomUUID().toString().replace("-", "");
					String query1 = "UPDATE INCOMINGS" +
					" SET STATUS = ?, TOKEN = ?" + 
					" WHERE ID = ?" ;
                     st = conn.prepareStatement(query1);
                     st.setInt(1, Integer.valueOf(orderStatus));
                     st.setString(2, token);
                     st.setInt(3, Integer.valueOf(transId));
					String query2 = "INSERT INTO" +
					" CHECKOUTS (ID, CONTENT_ID, CONTENT_TYPE, CONTENT_NAME, CONTENT_PRICE, RETURN_URL, TOKEN, STATUS, CP_ID)" +
					" VALUES (?,?,?,?,?,?,?,?,?)";
                    st1 = conn.prepareStatement(query2);
                    st1.setInt(1, Integer.valueOf(transId));
                    st1.setInt(2, Integer.valueOf(contentId));
                    st1.setInt(3, Integer.valueOf(contentType));
                    st1.setString(4, contentName);
                    st1.setInt(5, Integer.valueOf(contentPrice));
                    st1.setString(6, returnURL);
                    st1.setString(7, token);
                    st1.setInt(8, Integer.valueOf(orderStatus));
                    st1.setInt(9, Integer.valueOf(cpId));
					st.executeUpdate();
					st1.executeUpdate();
					/* Prase Object to Json 
					 * 
					 */
					Transaction t = new Transaction();
					t.setId(transId);
					t.setCpid(cpId);
					t.setContentid(contentId);
					t.setContentname(contentName);
					t.setContenttype(contentType);
					t.setContentprice(Integer.parseInt(contentPrice));
					t.setToken(token);
					t.setStatus(StaticVar.ERROR_ORDERED);
					Util.printJson(StaticVar.ERROR_ORDERED, t, resp);	

					log.info(StaticVar.ERROR_ORDERED + ";" + transId + ";" + token + ";" + req.getQueryString());			
				} catch (Exception e) {
					log.error("Error", e);
					Util.printJson(StaticVar.ERROR_INTERNAL_ERROR, null, resp);	
					return;
				} finally {
					try {
						if (st != null)	st.close();
						if (st1 != null)	st.close();
						if (conn != null) Database.closeConnection(conn);
					} catch (Exception e) {
						log.error("Error", e);
					}
				}
			}
		}
	}
}
